#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import time
try:
    _path = os.path.abspath(os.path.dirname(__file__))
    execfile('%s/venv/bin/activate_this.py'%_path, dict(__file__='%s/venv/bin/activate_this.py'%_path))
except:
    pass
from toughlib import choosereactor
choosereactor.install_optimal_reactor(False)
import sys,signal,click
import platform as pf
sys.path.insert(0,os.path.split(__file__)[0])
from twisted.internet import reactor
from twisted.python import log
from toughlib import config as iconfig
from toughlib import dispatch,logger,utils
from toughlib.dbengine import get_engine
from toughradius.manage import settings
from toughradius.manage.settings import redis_conf
from toughradius.common import log_trace
from toughradius import __version__

reactor.suggestThreadPoolSize(30)

def setup_logger(config):
    syslog = logger.Logger(config,'radius')
    dispatch.register(syslog)
    log.startLoggingWithObserver(syslog.emit, setStdout=0)
    return syslog

def update_timezone(config):
    if 'TZ' not in os.environ:
        os.environ["TZ"] = config.system.tz
    try:time.tzset()
    except:pass

def reactor_run():
    def ExitHandler(signum, stackframe):
        print "Got signal: %s" % signum
        reactor.callFromThread(reactor.stop)
    signal.signal(signal.SIGTERM, ExitHandler)
    reactor.run()

def print_version(ctx, param, value):
    if not value or ctx.resilient_parsing:
        return
    click.echo(click.style("ToughRADIUS {0}".format(__version__),fg='cyan'))
    ctx.exit()

def print_info(ctx, param, value):
    if not value or ctx.resilient_parsing:
        return
    click.echo(click.style("Linux distribution: {0}".format(','.join(pf.linux_distribution())),fg='cyan'))
    click.echo(click.style("ToughRadius version: {0}".format(__version__),fg='cyan'))
    click.echo(click.style("Env_home: {0}".format(os.environ.get("HOME")),fg='cyan'))
    click.echo(click.style("Env_path: {0}".format(os.environ.get("PATH")),fg='cyan'))
    click.echo(click.style("Server platform: {0},{1}".format(pf.platform(),pf.machine()),fg='cyan'))
    click.echo(click.style("Python version: {0},{1}".format(pf.python_implementation(), pf.python_version()),fg='cyan'))
    ctx.exit()


@click.group()
@click.option('--version', is_flag=True, callback=print_version,expose_value=False, is_eager=True)
@click.option('--info', is_flag=True, callback=print_info,expose_value=False, is_eager=True, help="server info")
def cli():
    pass


@click.command()
@click.option('-c','--conf', default='/etc/toughradius.json', help='config file')
@click.option('-d','--debug', is_flag=True)
@click.option('-t','--start-taskd', is_flag=True, help="start taskd process")
def manage(conf,debug,start_taskd):
    """ 启动管理控制台 """
    from toughradius.manage import httpd
    from toughradius.manage import taskd
    config = iconfig.find_config(conf)
    update_timezone(config)
    if debug:
        config.system.debug = True
    dbengine = get_engine(config)
    setup_logger(config)
    httpd.run(config,dbengine)
    if start_taskd:
        taskd.run(config,dbengine)
    reactor_run()


@click.command()
@click.option('-c','--conf', default='/etc/toughradius.json', help='config file')
@click.option('-d','--debug', is_flag=True)
@click.option('-auth','--start-auth', is_flag=True, help="start radisu auth listen process")
@click.option('-acct','--start-acct', is_flag=True, help="start radius acct listen process")
@click.option('-worker','--start-worker', is_flag=True, help="start radius worker process")
def radiusd(conf,debug,start_auth,start_acct,start_worker):
    """ 启动 Radiusd 服务 """
    from toughradius.manage import radiusd
    from toughradius.manage import taskd
    from toughlib.redis_cache import CacheManager
    config = iconfig.find_config(conf)
    update_timezone(config)
    if debug:
        config.system.debug = True
    dbengine = get_engine(config)
    cache = CacheManager(redis_conf(config),cache_name='RadiusCache')
    aes = utils.AESCipher(key=config.system.secret)
    log = setup_logger(config)
    if start_auth:
        radiusd.run_auth(config)
    if start_acct:
        radiusd.run_acct(config)
    if start_worker:
        radiusd.run_worker(config,dbengine,cache=cache,aes=aes,standalone=True)
    reactor_run()



@click.command()
@click.option('-c','--conf', default='/etc/toughradius.json', help='config file')
@click.option('-d','--debug', is_flag=True)
def task(conf,debug):
    """ 启动定时任务 """
    from toughradius.manage import taskd
    config = iconfig.find_config(conf)
    update_timezone(config)
    if debug:
        config.system.debug = True
    dbengine = get_engine(config)
    setup_logger(config)
    taskd.run(config,dbengine)
    reactor_run()


@click.command()
@click.option('-c','--conf', default='/etc/toughradius.json', help='config file')
@click.option('-d','--debug', is_flag=True)
def auth(conf,debug):
    """ 启动 Radius 认证监听 """
    from toughradius.manage import radiusd
    config = iconfig.find_config(conf)
    update_timezone(config)
    if debug:
        config.system.debug = True
    dbengine = get_engine(config)
    setup_logger(config)
    radiusd.run_auth(config)
    reactor_run()


@click.command()
@click.option('-c','--conf', default='/etc/toughradius.json', help='config file')
@click.option('-d','--debug', is_flag=True)
def acct(conf,debug):
    """ 启动 Radius 记账监听 """
    from toughradius.manage import radiusd
    config = iconfig.find_config(conf)
    update_timezone(config)
    if debug:
        config.system.debug = True
    dbengine = get_engine(config)
    setup_logger(config)
    radiusd.run_acct(config)
    reactor_run()


@click.command()
@click.option('-c','--conf', default='/etc/toughradius.json', help='config file')
@click.option('-d','--debug', is_flag=True)
@click.option('-n','--num', default=2,type=click.INT)
def worker(conf,debug,num):
    """ 启动 Radius 消息处理器 """
    from toughradius.manage import radiusd
    config = iconfig.find_config(conf)
    update_timezone(config)
    if debug:
        config.system.debug = True
    dbengine = get_engine(config)
    setup_logger(config)
    radiusd.run_worker(config,dbengine)
    reactor_run()

@click.command()
@click.option('-c','--conf', default='/etc/toughradius.json', help='config file')
@click.option('-f','--force', is_flag=True)
def initdb(conf,force):
    """ 初始化数据库 """
    from toughradius.common import initdb as init_db
    config = iconfig.find_config(conf)
    init_db.update(config,force=force)

@click.command()
@click.option('-c','--conf', default='/etc/toughradius.json', help='config file')
@click.option('-f','--force', is_flag=True)
def inittest(conf,force):
    """ 初始化测试数据 """
    from toughradius.common import inittest as init_test
    config = iconfig.find_config(conf)
    init_test.update(config)

@click.command()
@click.option('-c','--conf', default='/etc/toughradius.json', help='config file')
@click.option('-d','--debug', is_flag=True)
@click.option('--exitwith', default=0,type=click.INT, help='exit after sec')
def standalone(conf,debug,exitwith):
    """ 启动单进程模式 """
    from toughradius.manage import httpd
    from toughradius.manage import radiusd
    from toughradius.manage import taskd
    from toughlib.redis_cache import CacheManager
    config = iconfig.find_config(conf)
    update_timezone(config)
    if debug:
        config.system.debug = True
    dbengine = get_engine(config)
    cache = CacheManager(redis_conf(config),cache_name='RadiusCache')
    aes = utils.AESCipher(key=config.system.secret)
    log = setup_logger(config)
    httpd.run(config,dbengine,cache=cache,aes=aes)
    radiusd.run_auth(config)
    radiusd.run_acct(config)
    radiusd.run_worker(config,dbengine,cache=cache,aes=aes,standalone=True)
    taskd.run(config,dbengine,cache=cache,aes=aes,standalone=True)
    if exitwith > 0:
        print "testing application running and exit after %s seconds" % exitwith
        reactor.callLater(exitwith,reactor.stop)
    reactor_run()


cli.add_command(manage)
cli.add_command(radiusd)
cli.add_command(task)
cli.add_command(auth)
cli.add_command(acct)
cli.add_command(worker)
cli.add_command(initdb)
cli.add_command(inittest)
cli.add_command(standalone)

if __name__ == '__main__':
    cli()







